/*************************************************************************
  > File Name: memcheck.c
  > Author: QiyangXia
  > Mail: 834061456@qq.com 
  > Created Time: 2022年01月22日 星期六 17时16分36秒
 ************************************************************************/
#include "memcheck.h"

#ifdef MEM_CHECK 
/*做动态检查时参与编译的代码*/

#define OVERSTEP_VALUE  0xdeadbeaf
#define SRC_FILENAME_LEN 64

#define print() printf("in %s at %d\n",__FILE__,__LINE__)
struct mem_node
{
	int size;
	void *pdy;
	char srcfile[SRC_FILENAME_LEN];
	int lineno;

	struct mem_node *pnext;
	struct mem_node *pprev;
};

struct mem_list
{
	int len;
	struct mem_node *pfirst;
};

static struct mem_node * remove_at_head(struct mem_list *phead);
static int remove_a_node(struct mem_list *phead,struct mem_node *pnode);
static int insert_a_node(struct mem_list *phead,struct mem_node *pnode);
static struct mem_node *create_mem_node(void *paddr,int size,char *cfilename,int lineno);
static int destroy_mem_node(struct mem_node *pnode);
static struct mem_node *search_mem_node_by_addr(struct mem_list *phead,void *paddr);

static struct mem_list gmemlist;


int clear_memlist(void  *plist)
{
	struct mem_list *phead = (struct mem_list *)plist;
	/*清空链表*/
	struct mem_node *pnode = NULL;
	struct mem_node *pnext = NULL;

	pnode = phead->pfirst;
	while(pnode != NULL)
	{
		pnext = pnode->pnext;
		pnode->pnext=NULL;
		pnode->pprev=NULL;
		pnode = pnext;
	}

	phead->pfirst = NULL;
	phead->len = 0;

	return 0;
}

void *my_malloc_private(int size,char *cfilename,int lineno)
{
	void *p = NULL;
	void *ptemp=NULL;
	unsigned int *pt=NULL;
	/*1. malloc size + 4 + 4 + 4 bytes*/	
	p=malloc(size + 12);
	if(NULL==p)
	{
		print();
		return NULL;
	}
	/* 前4字节填size */
	*(int *)p=size;
	/* 紧接着4字节填OVERSTEP_VALUE */
	pt=(unsigned int *)((char *)p+4);
	*pt=OVERSTEP_VALUE;
	/* 最后4个字节填OVERSTEP_VALUE*/
	pt=(unsigned int *)((char *)p+8+size);
	*pt=OVERSTEP_VALUE;

	p = (char *)p + 8;
	/*2. 创建新节点*/
	struct mem_node *pnew=NULL;
	pnew=create_mem_node(p,size,cfilename,lineno);
	/*3. 插入新节点*/
	insert_a_node(&gmemlist,pnew);

	return p;
}

int my_free_private(void *p,char *cfilename,int lineno)
{
	/*1. 查找节点*/
	struct mem_node *ptemp=NULL;
	ptemp = search_mem_node_by_addr(&gmemlist,p);
	if(NULL==ptemp)
	{
		print();
		return 1;
	}
	/*2. 输出释放相关的信息：哪个文件的哪行释放了哪个文件的哪行动态分配的内存*/
	printf("执行代码程序名：%s  执行程序行号： %d\n",cfilename,lineno);
	printf("空间的程序名：%s  空间的行号： %d\n",ptemp->srcfile,ptemp->lineno);
	/*3. 移除节点*/
	remove_a_node(&gmemlist,ptemp);
	/*4. 销毁节点*/
	destroy_mem_node(ptemp);
	/*5. 释放p指向空间 free((char *)p-8)*/
	free((char *)p-8);
	p=NULL;
	return 0;
}

int check_mem_leak()
{
	/*输出剩余节点信息，每个节点意味着有内存未被释放*/
	struct mem_node *pnode = gmemlist.pfirst;
	if(pnode==NULL)
	{
		printf("all done\n");
		return 1;
	}
	while(pnode!=NULL)
	{
		printf("####################################################\n");
		printf("占有分配空间的程序名：%s 产生空间的行号：%d\n",pnode->srcfile,pnode->lineno);
		pnode=pnode->pnext;
	}
	return 0;
}

int check_mem_overstep(void *paddr)
{

	unsigned int beforeval=0;
	unsigned int afterval=0;
	char *pt=NULL;
	if(NULL==paddr)
	{
		print();
		return 1;
	}
	beforeval=*((unsigned int*)((char *)paddr-4));
	pt=(char *)paddr-8;

	pt=(char *)paddr+*(unsigned int *)pt;

	afterval=*((unsigned int *)pt);

	if(beforeval==OVERSTEP_VALUE&&afterval==OVERSTEP_VALUE)
	{
		printf("There is no overstep \n");
	}else{
		printf("Overstep!!!\n");
	}
	return 0;

}

static struct mem_node *create_mem_node(void *paddr,int size,char *cfilename,int lineno)
{
	struct mem_node *pnew=NULL;
	pnew=(struct mem_node *)malloc(sizeof(struct mem_node));
	if(NULL==pnew)
	{
		print();
		return NULL;
	}
	memset(pnew,0,sizeof(struct mem_node));

	pnew->size=size;
	pnew->pdy=paddr;
	strcpy(pnew->srcfile,cfilename);
	pnew->lineno=lineno;

	return pnew;

}

static int destroy_mem_node(struct mem_node *pnode)
{
	if(pnode!=NULL)
	{
		free(pnode);
		pnode=NULL;
	}
	return 0;
}

static struct mem_node *search_mem_node_by_addr(struct mem_list *phead,void *paddr)
{
	char *ptemp =(char *)paddr;
	struct mem_node *pt=NULL;
	pt=phead->pfirst;
	if(pt==NULL)
	{
		print();
		return NULL;
	}

	while((char *)(pt->pdy)!=ptemp)
	{
		pt=pt->pnext;
		if(NULL==pt)
		{
			break;
		}
	}
	return pt;
}

static int insert_a_node(struct mem_list *phead,struct mem_node *pnew)
{  
	if(NULL==phead||NULL==pnew)
	{
		print();
		return -1;
	}
	pnew->pnext=phead->pfirst;
	pnew->pprev=NULL;

	if(phead->pfirst!=NULL)
	{
		phead->pfirst->pprev=pnew;
	}else{
		pnew->pnext=NULL;
	}

	phead->pfirst=pnew;

	phead->len++;
	return 0;
}


static int remove_a_node(struct mem_list *phead,struct mem_node *pnode)
{
	struct mem_node *ptemp = NULL;
	ptemp=phead->pfirst;

	if(NULL == phead || NULL == pnode||NULL==ptemp)
	{
		print();
		return -1;
	}
	while(ptemp!=pnode)
	{
		ptemp=ptemp->pnext;
		if(NULL==ptemp)
		{
			break;
		}
	}
	if(pnode->pnext!=NULL)
	{
		pnode->pnext->pprev=pnode->pprev;
	}
	pnode->pprev->pnext=pnode->pnext;
	pnode->pnext=NULL;
	pnode->pprev=NULL;

	return 0;
}

#else
/*不做动态检查时参与编译的代码*/
int clear_memlist(void  *plist)
{
	return 0;
}

int check_mem_leak()
{
	return 0;
}

int check_mem_overstep(void *paddr)
{

}
#endif
